/*
 * File: Trip.java Author: Robert Bittle <guywithnose@gmail.com>
 */
package triperest;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * The Class Trip.
 */
public class Trip implements DataObject
{

    /** The ID. */
    private long ID = 0;

    /** The name. */
    private String name;

    /** The description. */
    private String description;

    /** The destinations. */
    private ArrayList<Destination> destinations = new ArrayList<Destination>();

    /**
     * Instantiates a new trip.
     * 
     * @param id
     *            the id
     */
    public Trip(long id)
    {
        ID = id;
        load();
    }

    /**
     * Instantiates a new trip.
     */
    public Trip()
    {

    }

    /**
     * Get Id.
     * 
     * @return the id
     */
    public long getId()
    {
        return this.ID;
    }

    /**
     * Get Destinations.
     * 
     * @return the destinations
     */
    public ArrayList<Destination> getDestinations()
    {
        return this.destinations;
    }

    /**
     * Adds the destination.
     * 
     * @param destination
     *            the destination
     */
    public void addDestination(Destination destination)
    {
        Iterator<Destination> i = destinations.iterator();
        while (i.hasNext())
        {
            Destination d = i.next();
            if (d.getID() == destination.getID())
            {
                return;
            }
        }
        this.destinations.add(destination);
    }

    /**
     * Removes the destination.
     * 
     * @param destinationId
     *            the destination id
     */
    public void removeDestination(long destinationId)
    {
        Iterator<Destination> i = destinations.iterator();
        while (i.hasNext())
        {
            Destination d = i.next();
            if (d.getID() == destinationId)
            {
                this.destinations.remove(d);
            }
        }
    }

    /**
     * Clear destinations.
     */
    public void clearDestinations()
    {
        this.destinations.clear();
    }

    /**
     * Get Name.
     * 
     * @return the name
     */
    public String getName()
    {
        return name;
    }

    /**
     * Sets the name.
     * 
     * @param Name
     *            the new name
     */
    public void setName(String Name)
    {
        this.name = Name;
    }

    /**
     * Get Description.
     * 
     * @return the description
     */
    public String getDescription()
    {
        return description;
    }

    /**
     * Sets the description.
     * 
     * @param Description
     *            the new description
     */
    public void setDescription(String Description)
    {
        this.description = Description;
    }

    /**
     * Checks if is this mine.
     * 
     * @param user
     *            the user
     * @return true, if is this mine
     */
    public boolean isThisMine(TriperestUser user)
    {
        Iterator<Trip> i = user.getTrips().iterator();
        while(i.hasNext())
        {
            if(i.next().getId() == ID)
                return true;
        }
        return false;
    }

    /*
     * (non-Javadoc)
     * 
     * @see java.lang.Object#clone()
     */
    @Override
    public Trip clone()
    {
        Trip newTrip = new Trip();
        newTrip.setDescription(description);
        newTrip.setName(name);
        for (int i = 0; i < destinations.size(); i++)
        {
            newTrip.addDestination(destinations.get(i));
        }
        return newTrip;
    }

    /*
     * (non-Javadoc)
     * 
     * @see triperest.DataObject#delete()
     */
    @Override
    public boolean delete()
    {
        try
        {
            if (DataConnection.connect())
            {
                String statement = "delete from trip where trip_id = ?";
                PreparedStatement stmt = DataConnection.getConnection()
                        .prepareStatement(statement);
                stmt.setLong(1, ID);
                int success = 2;
                stmt.executeUpdate();
                Iterator<Long> j = loadDestIds().iterator();
                while (j.hasNext())
                {
                    deleteDestId(j.next());
                }
                return success == 1;
            }
        } catch (SQLException e)
        {
            e.printStackTrace();
        }
        return true;
    }

    /*
     * (non-Javadoc)
     * 
     * @see triperest.DataObject#save()
     */
    @Override
    public boolean save()
    {
        try
        {

            if (ID != 0)
            {
                return update();
            }
            return insert();
        } catch (SQLException e)
        {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Update.
     * 
     * @return true, if successful
     * @throws SQLException
     *             the SQL exception
     */
    private boolean update() throws SQLException
    {
        if (DataConnection.connect())
        {
            String statement = "update trip set name = ?, description = ? where trip_id = ?";
            PreparedStatement stmt = DataConnection.getConnection()
                    .prepareStatement(statement);
            stmt.setString(1, name);
            stmt.setString(2, description);
            stmt.setLong(3, ID);
            int success = 2;
            stmt.executeUpdate();
            saveDestinations();
            return success == 1;
        }
        return false;
    }

    /**
     * Update.
     * 
     * @return true, if successful
     * @throws SQLException
     *             the sQL exception
     */
    private boolean insert() throws SQLException
    {
        if (DataConnection.connect())
        {
            String statement = "INSERT INTO trip (name, description) VALUES ( ? , ? )";
            PreparedStatement stmt = DataConnection.getConnection()
                    .prepareStatement(statement,
                            Statement.RETURN_GENERATED_KEYS);
            stmt.setString(1, name);
            stmt.setString(2, description);
            int success = 2;
            stmt.executeUpdate();
            ResultSet key = stmt.getGeneratedKeys();
            if (key.next())
            {
                ID = key.getLong(1);
                saveDestinations();
            }
            return success == 1;
        }
        return false;
    }

    /**
     * Save destinations.
     * 
     * @throws SQLException
     *             the sQL exception
     */
    private void saveDestinations() throws SQLException
    {
        ArrayList<Long> destIds = loadDestIds();
        for(int i = 0; i < destinations.size(); i++)
        {
            destinations.get(i).save();
            if (destIds.contains(destinations.get(i).getID()))
            {
                destIds.remove(destinations.get(i).getID());
            } else
            {
                saveDestId(destinations.get(i).getID(), i);
            }
        }
        Iterator<Long> j = destIds.iterator();
        while (j.hasNext())
        {
            deleteDestId(j.next());
        }
    }

    /**
     * Save dest id.
     * 
     * @param destId
     *            the dest id
     * @throws SQLException
     *             the sQL exception
     */
    private void saveDestId(long destId, int index) throws SQLException
    {
        if (DataConnection.connect())
        {
            String statement = "INSERT INTO trip_dest (trip_id, dest_id, ind) VALUES ( ? , ? , ? )";
            PreparedStatement stmt = DataConnection.getConnection()
                    .prepareStatement(statement);
            stmt.setLong(1, ID);
            stmt.setLong(2, destId);
            stmt.setInt(3, index);
            stmt.executeUpdate();
        }
    }

    /**
     * Delete dest id.
     * 
     * @param destId
     *            the dest id
     * @throws SQLException
     *             the sQL exception
     */
    private void deleteDestId(long destId) throws SQLException
    {
        if (DataConnection.connect())
        {
            String statement = "delete from trip_dest where trip_id = ? and dest_id = ?";
            PreparedStatement stmt = DataConnection.getConnection()
                    .prepareStatement(statement);
            stmt.setLong(1, ID);
            stmt.setLong(2, destId);
            stmt.executeUpdate();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see triperest.DataObject#load()
     */
    @Override
    public boolean load()
    {
        try
        {
            if (DataConnection.connect())
            {
                String statement = "select name, description from trip where trip_id = ?";
                PreparedStatement stmt = DataConnection.getConnection()
                        .prepareStatement(statement);
                stmt.setLong(1, ID);
                ResultSet results = stmt.executeQuery();
                if (results.next())
                {
                    name = results.getString("name");
                    description = results.getString("description");
                    Iterator<Long> i = loadDestIds().iterator();
                    while (i.hasNext())
                    {
                        destinations.add(new Destination(i.next()));
                    }
                    return true;
                }
            }
        } catch (SQLException e)
        {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Load dest ids.
     * 
     * @return the array list
     */
    private ArrayList<Long> loadDestIds()
    {
        ArrayList<Long> destIds = new ArrayList<Long>();
        try
        {
            if (DataConnection.connect())
            {
                String statement = "select dest_id, ind from trip_dest where trip_id = ?";
                PreparedStatement stmt = DataConnection.getConnection()
                        .prepareStatement(statement);
                stmt.setLong(1, ID);
                ResultSet results = stmt.executeQuery();
                while (results.next())
                {
                    destIds.add(results.getInt("ind"), results.getLong("dest_id"));
                }
            }
        } catch (SQLException e)
        {
            e.printStackTrace();
        }
        return destIds;
    }

    /**
     * Find trips.
     * 
     * @param parameter
     *            the parameter
     * @return the array list
     */
    public static ArrayList<Trip> findTrips(String parameter)
    {
        ArrayList<Trip> matchingTrips = new ArrayList<Trip>();
        Iterator<Trip> i = getAllTrips().iterator();
        while (i.hasNext())
        {
            Trip trip = i.next();
            if (trip.getName().contains(parameter)
                    || trip.getDescription().contains(parameter))
            {
                matchingTrips.add(trip);
            }
        }
        return matchingTrips;
    }

    /**
     * Get All destinations.
     * 
     * @return the all destinations
     */
    public static ArrayList<Trip> getAllTrips()
    {
        ArrayList<Trip> trips = new ArrayList<Trip>();
        try
        {
            if (DataConnection.connect())
            {
                String statement = "select trip_id from trip";
                PreparedStatement stmt = DataConnection.getConnection()
                        .prepareStatement(statement);
                ResultSet results = stmt.executeQuery();
                while (results.next())
                {
                    trips.add(new Trip(results.getLong("trip_id")));
                }
            }
        } catch (SQLException e)
        {
            e.printStackTrace();
        }
        return trips;
    }

}